package br.com.wai2008.socket.service;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;

import comum.Localizacao;

import servidor.Servidor;
import servidor.ServidorImpl;
import br.com.wai2008.socket.contextInformation.ContextInformation;
import br.com.wai2008.socket.dataobject.WAINetworkObject;
import br.com.wai2008.socket.dataobject.WAIServiceObject;
import br.com.wai2008.socket.direction.Direction;
import br.com.wai2008.socket.position.PositionEstimation;

/**
 * This class implements the execution for the services. It also calls
 * the position estimation, to get the estimation for the position of a 
 * device based on the wireless signal, and the route tracing, to verify 
 * if the route is right or if the device need to change the route.<br>
 * It also calls the service to get context information of the estimated
 * position.
 * 
 * @since 
 * 		September, 2008.
 * 
 * @version
 * 		WAI2008 - version 1.0
 * 
 * @author 
 * 		Andre Romero Goncales
 */
public class WAIService {

	/**
	 * Data Object from service.
	 */
	private WAIServiceObject dataObject;
	
	/**
	 * Executes the WAI service.<br>
	 * Based on the wireless signals from a device,
	 * this method calls the necessary methods to get the route that this 
	 * device need to follow and the context information from the estimated
	 * position.
	 * 
	 * @see 
	 * 		br.com.wai2008.socket.protocol.ClientToServerProtocol
	 * 
	 * @param
	 * 		scProtocol message received from the client. This message must be in a 
	 * 		ClientToServerProtocol protocol and contain the access points IDS and its 
	 * 		signals, the HD serial number for the device and the language for 
	 * 		context informations.
	 * 
	 * @return
	 * 		Message to be sent to the client. This message must be in a 
	 * 		ClientToServerProtocol protocol and contain the route that the device 
	 * 		need to follow.
	 */
	public String execute(String scProtocol) {
		String message = null;
		System.out.println("[WAIService] Executing...");
		System.out.println("[WAIService] Building DataObject...");
		this.dataObject = WAIProtocolManipulation.getDataObjectFromClientMessage(scProtocol);
		if (this.dataObject == null) {
			return WAIProtocolManipulation.getErrorMessageFromClientMessage();
		}
		System.out.println("[WAIService] DataObject built...");
		if (!dataObject.isSimulation()) {
			System.out.println("[WAIService] Calling position estimation...");
			PositionEstimation position = new PositionEstimation();
			String xyMessage = position.getPosition(WAIProtocolManipulation.getMessageToEstimatePositionServer(this.dataObject));
			System.out.println("[WAIService] Position estimation executed...");
			if (xyMessage != null) {
				String[] xy = WAIProtocolManipulation.getEstimatedPositionFromMessageReturned(xyMessage);
				if (xy != null) {
					this.dataObject.setInitialLocalization(xy[0], xy[1]);
					Servidor guiaMenosServer = new ServidorImpl();
					
					Localizacao destino = guiaMenosServer.pegaLocalizacaoPeloNome(this.dataObject.getTargetName());
					this.dataObject.setTargetLocalization(destino);
					Localizacao[] oldRoute =  ServidorImpl.getRotas(this.dataObject.getHdSerial());
					this.dataObject.setRoute(guiaMenosServer.calculaRota(this.dataObject.getInitialLocalization().obterLocalizacao(), 
							this.dataObject.getTargetLocalization(), this.dataObject.getRestriction(), this.dataObject.getHdSerial()));
					if (this.dataObject.getRoute() != null) {
						//direction
						new Direction().setDirection(this.dataObject.getRoute(), oldRoute, this.dataObject.getLanguage());
						int i=0;
						for (Localizacao l : this.dataObject.getRoute()) {							
							System.out.println("DEBUG Localizacao(" + i + "): (" + l.getX() + ", " + l.getY() + ", " + l.getAndar() + ")");
							i++;
						}
						this.dataObject.setMessage(new ContextInformation().getInformation(this.dataObject.getRoute(), 
								this.dataObject.getLanguage()));
						//this.dataObject.setMessage("Mensagem teste.");
						message = WAIProtocolManipulation.getMessageToClient(this.dataObject);
					} else {
						message = WAIProtocolManipulation.getErrorMessageFromGuiaMenos();
					}
				} else {
					message = WAIProtocolManipulation.getErrorMessageFromEstimatePositionServer();
				}
			} else {
				message = WAIProtocolManipulation.getErrorMessageFromEstimatePositionServer();
			}
			this.printFile();
		} else {
			//simulation
			System.out.println("IS SIMULATION");
			Servidor guiaMenosServer = new ServidorImpl();
			
			Localizacao destino = guiaMenosServer.pegaLocalizacaoPeloNome(this.dataObject.getTargetName());
			this.dataObject.setTargetLocalization(destino);
			Localizacao[] oldRoute =  ServidorImpl.getRotas(this.dataObject.getHdSerial());
			
			this.dataObject.setRoute(guiaMenosServer.calculaRota(this.dataObject.getInitialLocalization().obterLocalizacao(), 
					this.dataObject.getTargetLocalization(), this.dataObject.getRestriction(), this.dataObject.getHdSerial()));
			if (this.dataObject.getRoute() != null) {
				//direction
				new Direction().setDirection(this.dataObject.getRoute(), oldRoute, this.dataObject.getLanguage());
				int i=0;
				for (Localizacao l : this.dataObject.getRoute()) {							
					System.out.println("DEBUG Localizacao(" + i + "): (" + l.getX() + ", " + l.getY() + ", " + l.getAndar() + ")");
					i++;
				}
				this.dataObject.setMessage(new ContextInformation().getInformation(this.dataObject.getRoute(),
						this.dataObject.getLanguage()));
				//this.dataObject.setMessage("Mensagem teste.");
				message = WAIProtocolManipulation.getMessageToClient(this.dataObject);
			} else {
				message = WAIProtocolManipulation.getErrorMessageFromGuiaMenos();
			}
		}
		System.out.println("[WAIService] Executed");
		return message;
	}
	
	private void printFile() {
		try {
			File file  = new File("/romeroWorkspace/Logs/Sinais.txt");
			BufferedWriter buffer = new BufferedWriter(new FileWriter(file, true));
			Date date = new Date();
			buffer.write(date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds() + "\t");
			buffer.write(dataObject.getInitialLocalization().obterLocalizacao().getX() + "\t" +
					dataObject.getInitialLocalization().obterLocalizacao().getY() + "\t");
			boolean first = true;
			for (WAINetworkObject object : dataObject.getNetwork()) {
				if (first) {
					first = false;
				} else {
				}
				buffer.write(object.getId() + "\t" + object.getSignal() + "\t");
			}
			buffer.write("\n");
			buffer.flush();
			buffer.close();
			
		} catch (FileNotFoundException e) {
			System.out.println("ERROR: Arquivo para LOG nao encontrado;");
		} catch (IOException e) {
			System.out.println("ERROR: Arquivo para LOG nao encontrado;");
		}
	}
}
